package com.tanggh.dao.impl;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import javax.annotation.Resource;
import javax.persistence.Id;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.tanggh.dao.GenericDao;

@SuppressWarnings("unchecked")
public abstract class GenericDaoImpl<M extends java.io.Serializable> implements GenericDao<M> {
	private String pkName = null;
	private final String HQL_LIST_ALL;
	private final String HQL_LIST_ALL_DESC;
	private final String HQL_COUNT_ALL;
	private final Class<M> clazz;

	@Resource(name = "sessionFactory")
	private SessionFactory sessionFactory;

	public GenericDaoImpl() {
		clazz = (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		Field[] fields = clazz.getDeclaredFields();
		for (Field f : fields) { //注解定义在字段上
			if (f.isAnnotationPresent(Id.class)) {
				pkName = f.getName();
				break;
			}
		}
		if (pkName == null) { //注解定义在get方法上
			Method[] methods = clazz.getMethods();
			for(Method m : methods) {
				if(m.isAnnotationPresent(Id.class)) {
					String name = m.getName();
					pkName = name.substring(3);
					break;
				}
			}
		}

		HQL_LIST_ALL = "from " + this.clazz.getSimpleName() + " order by " + pkName;
		HQL_LIST_ALL_DESC = "from " + this.clazz.getSimpleName() + " order by " + pkName + " desc";
		HQL_COUNT_ALL = " select count(*) from " + clazz.getSimpleName();
		System.out.println("GenericDaoImpl.GenericDaoImpl() HQL_LIST_ALL:" + HQL_LIST_ALL);
	}

	public Session getSession() {
		// return sessionFactory.getCurrentSession();
		return sessionFactory.openSession();
	}

	@Override
	public int countAll() {
		Query query = getSession().createQuery(HQL_COUNT_ALL);
		return (Integer) query.uniqueResult();
	}

	@Override
	public void delete(Integer id) {
		getSession().delete(get(id));
	}

	@Override
	public void deleteObject(M model) {
		getSession().delete(model);
	}

	@Override
	public M get(Integer id) {
		return (M) getSession().get(clazz, id);
	}

	@Override
	public List<M> listAll() {
		Query query = getSession().createQuery(HQL_LIST_ALL);
		return query.list();
	}
	
	@Override
	public List<M> descListAll() {
		Query query = getSession().createQuery(HQL_LIST_ALL_DESC);
		return query.list();
	}

	@Override
	public void merge(M model) {
		getSession().merge(model);

	}

	@Override
	public Integer save(M model) {
		return (Integer) getSession().save(model);
	}

	@Override
	public void saveOrUpdate(M model) {
		getSession().saveOrUpdate(model);
	}

	@Override
	public void update(M model) {
		getSession().update(model);
	}

	public boolean exists(Integer id) {
		return get(id) != null;
	}

}
